// hande make two mod for rethinking the Serialize & Serializer interface design [ input & output parameter, type, imm/m/move,...]
// mod from_serde  Two Trait from Serde  and impl i32 support
// mod my_self  Two Trait from myself  and impl i32 support
// difference: 
//  [1]  replace Generic Type [S: Serializer] to Trait Object (s: dyn Serializer)
//  [2] input self: use self means call once 
//      , use &mut self call many times and change self

//  Two trait are  from  Serde::ser
pub mod from_serde {
    use std::io;
    use std::error;

    pub trait Serialize {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> //NOTE: [1] Use <S> to replace trait object 
        where 
            S: Serializer ;
    }
    pub trait Serializer {
        type Ok ;
        type Error: error::Error;
        fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>; //NOTE: [2] parameter:self, means serializer as self is moved, serializer just call once
    }

    pub fn to_string<T>(v: &T) -> Result<String, io::Error>
    where 
        T: Serialize
    {
        let mut serializer = XSerializer::new();
        T::serialize(v, &mut serializer)?;
        Ok(serializer.output)
    }

    struct XSerializer {
        output: String,
    }
    impl XSerializer {
        fn new() -> Self {
            Self  {
                output: String::new()
            }
        }
    }

    impl<'a> Serializer for &'a mut XSerializer {
        type Ok = ();
        type Error = io::Error;
        fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>{
            self.output += &v.to_string();
            Ok(())
        }
    }

    impl Serialize for i32 {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
        {
            serializer.serialize_i32(*self)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn i32_to_string() {
            let v: i32 = 1_i32;
            let expect = v.to_string();

            let result = to_string(&v).unwrap();
            assert_eq!(expect, result);
        }
    }
}  // mod from_serde

pub mod my_self {

    use std::io;
    use std::error;
    //declare traits
    //
    trait Serialize {
        fn serialize<S>(&self, serializer: &mut S) -> Result<S::Ok, S::Error>//NOTE: [1] use [S] to replace trait object is good
        where S : Serializer;
    }
    trait Serializer {
        type Ok;
        type Error: error::Error;
        //TODO: is self must be Mutable ?????
        fn serialize_i32(&mut self, v: i32)->Result<Self::Ok, Self::Error>; //NOTE: [2] parameter with mutable ref, no call once [move] concept
    }





    // impl Serialize for types
    impl Serialize for i32 {
        fn serialize<S>(&self, serializer: &mut S) -> Result<S::Ok, S::Error>
        where S: Serializer 
        {
            serializer.serialize_i32(*self)
        }
    }



    // impl Serializer for Gtp
    struct XSerializer {
        output: String,
    }

    impl XSerializer {
        fn new()-> Self {
            Self {
                output: String::new(),
            }
        }
    }

    impl Serializer for XSerializer {
        type Ok = ();
        type Error = io::Error;
        fn serialize_i32(&mut self, v: i32)->Result<Self::Ok, Self::Error>{
            self.output += &v.to_string();
            Ok(())
        }
    }

    // Gtp Serializer interface 
    pub fn to_string(v: &i32) -> Result<String, io::Error> {
        let mut serializer = XSerializer::new();
        v.serialize(&mut serializer)?;
        Ok(serializer.output)
    }
    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn i32_to_string() {
            let v: i32 = 1_i32;
            let expect = v.to_string();

            let result = to_string(&v).unwrap();
            assert_eq!(expect, result);
        }
    }
}//mod my_self



